﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.UI;
using Akso.Authorization;
using Akso.Entities;
using Akso.Vendors.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity;
using System.Linq.Dynamic;
using Abp.AutoMapper;
using Abp.Linq.Extensions;
using Abp.Extensions;
using Akso.Dto;
using Akso.Vendors.Exporting;
using System.Diagnostics;

namespace Akso.Vendors
{
    [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors)]
    public class VendorAppService : AbpZeroTemplateAppServiceBase, IVendorAppService
    {
        private readonly IRepository<Vendor, Guid> _vendorsRepository;
        private readonly IVendorListExcelExporter _vendorListExcelExporter;

        public VendorAppService(IRepository<Vendor, Guid> vendorsRepository,
            IVendorListExcelExporter vendorListExcelExporter)
        {
            _vendorsRepository = vendorsRepository;
            _vendorListExcelExporter = vendorListExcelExporter;
        }

        public async Task<PagedResultOutput<VendorListDto>> GetObjects(GetVendorsInput input)
        {
            var query = getQuery(input);
            var dataCount = await query.CountAsync();
            var data = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync();

            return new PagedResultOutput<VendorListDto>(
                dataCount,
                data.MapTo<List<VendorListDto>>()
                );
        }

        private IQueryable<Vendor> getQuery(GetVendorsInput input)
        {
            var query = _vendorsRepository.GetAll()
                .WhereIf(
                    !input.Filter.IsNullOrWhiteSpace(),
                    t =>
                        t.Name.Contains(input.Filter) ||
                        t.Address.Contains(input.Filter)
                );
            return query;
        }

        public async Task<FileDto> GetObjectsToExcel(GetVendorsInput input)
        {
            var query = getQuery(input);
            var vendors = await query.ToListAsync();
            var vendorListDtos = vendors.MapTo<List<ExportVendorDto>>();

            return _vendorListExcelExporter.ExportToFile(vendorListDtos);
        }

        [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors_Delete)]
        public async Task DeleteObject(IdInput<Guid> input)
        {
            var o = await _vendorsRepository.GetAsync(input.Id);
            await _vendorsRepository.DeleteAsync(o);
        }


        [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors_Create, AppPermissions.Pages_BasicData_Vendors_Edit)]
        public async Task<Vendor> CreateOrUpdateObject(CreateOrUpdateVendorInput input)
        {
            //var vendor = input.Vendor.MapTo<Vendor>();
            //return await _vendorsRepository.InsertOrUpdateAsync(vendor);
            if (input.Vendor.Id.HasValue)
            {
                return await UpdateObject(input);
            }
            else
            {
                return await CreateObject(input);
            }
        }

        [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors_Edit)]
        protected virtual async Task<Vendor> UpdateObject(CreateOrUpdateVendorInput input)
        {
            Debug.Assert(input.Vendor.Id != null, "input.Vendor.Id should be set.");

            var o = await _vendorsRepository.GetAsync(input.Vendor.Id.Value);
            //Update vendor properties
            input.Vendor.MapTo(o);
            return await _vendorsRepository.UpdateAsync(o);
        }

        [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors_Create)]
        protected virtual async Task<Vendor> CreateObject(CreateOrUpdateVendorInput input)
        {
            var o = input.Vendor.MapTo<Vendor>();
            return await _vendorsRepository.InsertAsync(o);
        }

        [AbpAuthorize(AppPermissions.Pages_BasicData_Vendors_Create, AppPermissions.Pages_BasicData_Vendors_Edit)]
        public async Task<GetVendorForEditOutput> GetObjectForEdit(NullableIdInput<Guid> input)
        {
            var output = new GetVendorForEditOutput
            {
                
            };

            if (!input.Id.HasValue)
            {
                //Creating a new object
                output.Vendor = new VendorEditDto();
            }
            else
            {
                //Editing an existing object
                var vendor = await _vendorsRepository.GetAsync(input.Id.Value);

                output.Vendor = vendor.MapTo<VendorEditDto>();
            }

            return output;
        }
    }
}
